package com.demo2do.fms.admin.service.supplier.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.demo2do.core.entity.exception.BusinessException;
import com.demo2do.core.entity.page.Page;
import com.demo2do.core.persistence.GenericDaoSupport;
import com.demo2do.core.persistence.annotation.Dao;
import com.demo2do.fms.admin.Constants;
import com.demo2do.fms.admin.dao.supplier.DriverDao;
import com.demo2do.fms.admin.dao.supplier.SupplierDao;
import com.demo2do.fms.admin.dao.vehicle.RemoteTransMeansDao;
import com.demo2do.fms.admin.dao.vehicle.VehicleDao;
import com.demo2do.fms.admin.dao.vehicle.VehicleLockRecordDao;
import com.demo2do.fms.admin.dao.vehicle.VehicleLockRecordDaoSupport;
import com.demo2do.fms.admin.dao.vehicle.VehicleSourceDao;
import com.demo2do.fms.admin.entity.search.supplier.AbnormalCapacitySearch;
import com.demo2do.fms.admin.entity.security.Login;
import com.demo2do.fms.admin.service.supplier.VehicleLockService;
import com.demo2do.fms.entity.driver.Driver;
import com.demo2do.fms.entity.driver.DriverAuditStatus;
import com.demo2do.fms.entity.supplier.common.Supplier;
import com.demo2do.fms.entity.vehicle.source.LockStatus;
import com.demo2do.fms.entity.vehicle.source.RemoteTransMeans;
import com.demo2do.fms.entity.vehicle.source.Vehicle;
import com.demo2do.fms.entity.vehicle.source.VehicleGpsInfo;
import com.demo2do.fms.entity.vehicle.source.VehicleSource;
import com.demo2do.fms.entity.vehicle.source.VehicleSourceLockRecord;

/**
 * 
 * @author mohanlan
 *
 */
@Service("vehicleLockService")
public class VehicleLockServiceImpl implements VehicleLockService {
    
    @Autowired
    private GenericDaoSupport genericDaoSupport;
    
    @Dao
    private RemoteTransMeansDao remoteTransMeansDao;
    
    @Dao
    private VehicleDao vehicleDao;
    
    @Dao
    private VehicleLockRecordDao vehicleLockRecordDao;
    
    @Dao
    private DriverDao driverDao;
    
    @Dao
    private SupplierDao supplierDao;
    
    @Dao
    private VehicleSourceDao vehicleSourceDao;
    
    @Autowired
    private VehicleLockRecordDaoSupport vehicleLockRecordDaoSupport;
    
    /*
     * (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.VehicleLockService#unlockVehicle(com.demo2do.fms.entity.vehicle.VehicleSource, com.demo2do.fms.entity.vehicle.LockType, java.lang.Long)
     */
    public void unlockVehicle(VehicleSource vehicleSource, Long operator, String description) {
        
    	Date now = new Date();
    	Date twoHoursBefore = DateUtils.addHours(now, -2);
    	
    	// 1. check whether can unlock
        String errorMessage = this.validUnlock(vehicleSource, twoHoursBefore);
        if(StringUtils.isNotBlank(errorMessage)) {
            throw BusinessException.newInstance("500", errorMessage);
        }
        
        // 2. unlock fms vehicle
        genericDaoSupport.update(vehicleSource.unlock(operator, now));
        
        // 3. unlock remote transMeans
        String vehicleCode = vehicleSource.getCode();
        RemoteTransMeans remoteTransMeans = remoteTransMeansDao.loadByCode(vehicleCode);
        if(remoteTransMeans == null) {
            throw new BusinessException("锁车数据信息为空");
        }
        
        genericDaoSupport.update(remoteTransMeans.unlock(Constants.MDM_LOCK_USERID));
        
        // 4. 创建解锁记录 
        this.createVehicleLockRecord(vehicleSource, LockStatus.UNLOCKED, description, operator);
        
    }
    
    /**
     * @param vehicleSource
     * @param twoHoursBefore
     * @return
     */
    private String validUnlock(VehicleSource vehicleSource, Date twoHoursBefore) {
        
        if(vehicleSource == null) {
            return "车辆状态不正常";
        }
        
        if(!vehicleSource.isSynchronize()) {
            return "车辆暂未同步";
        }
        
        if(StringUtils.isEmpty(vehicleSource.getCode())) {
            return "车辆缺失code，数据异常";
        }
        
        Vehicle vehicle = vehicleDao.loadByCode(vehicleSource.getCode());
        List<Driver> drivers = driverDao.listByVehicle(vehicle.getId(), DriverAuditStatus.QUALIFIED);
        if (CollectionUtils.isEmpty(drivers)) {
            return "车辆未和司机绑定";
        }
        
//        if(!this.hasLastTwoHourGpsInfo(vehicleSource, twoHoursBefore)) {
//            return "无最近两小时的GPS信息";
//        }
        
        return null;
        
    }
    
    /**
     * @param vehicleSource
     * @return
     */
    private boolean hasLastTwoHourGpsInfo(VehicleSource vehicleSource, Date twoHoursBefore) {
        
        // 1. get vw_vehicle info
    	String vehicleCode = vehicleSource.getCode();
    	Vehicle vehicle = vehicleDao.loadByCode(vehicleCode);
    	
    	// 2. get vw_vehicle whether has gps info in 2 hour
    	List<VehicleGpsInfo> infos = remoteTransMeansDao.listLatestGps(vehicle.getId(), twoHoursBefore);
        return CollectionUtils.isNotEmpty(infos);
        
    }
    
    /*
     * (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.VehicleLockService#listNeedLockVids(java.util.Date)
     */
    public List<Long> listNeedLockVids(Date date) {
        return remoteTransMeansDao.listNeedLockVids(date);
    }
    
    /*
     * (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.VehicleLockService#listNoGpsVids()
     */
    public List<Long> listNoGpsVids() { 
        return remoteTransMeansDao.listNoGpsVids();
    }
    
    /*
     * (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.VehicleLockService#listNoDriverVCodes()
     */
    public List<String> listNoDriverVCodes() {
        List<String> noDriverVCodes = vehicleDao.listNoDriverVCodes();
        return noDriverVCodes;
    }
    
    /*
     * (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.VehicleLockService#listNeedUnlockVids(java.util.Date)
     */
    public List<Long> listNeedUnlockVids(Date date) {
        return remoteTransMeansDao.listNeedUnlockVids(date);
    }
    
    /**
     * 
     * @param vehicleSource
     * @param status
     * @param description
     * @param operator
     */
    private void createVehicleLockRecord(VehicleSource vehicleSource, LockStatus status, String description, Long operator) {
        VehicleSourceLockRecord record = new VehicleSourceLockRecord(vehicleSource, status, description, operator);
        genericDaoSupport.save(record);
    }
    
    /*
     * (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.VehicleLockService#loadLockRecord(java.lang.Long)
     */
    public VehicleSourceLockRecord loadLockRecord(Long id) {
        return genericDaoSupport.load(VehicleSourceLockRecord.class, id);
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.VehicleLockService#countLockRecord(com.demo2do.fms.admin.entity.security.Login)
     */
    public int countLockRecord(Login login) {
    	
        if(!login.isSupplier()) {
        	
            return vehicleLockRecordDaoSupport.countVehicleLockRecord(LockStatus.LOCKED);
            
        } else {
        	
        	Supplier supplier = genericDaoSupport.load(Supplier.class, login.getSupplierId());
            return vehicleLockRecordDaoSupport.countVehicleLockRecord(supplier, LockStatus.LOCKED);
            
        }
        
    }
    
    /*
     * (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.VehicleLockService#countLockRecord(com.demo2do.fms.admin.entity.security.Login, com.demo2do.fms.entity.vehicle.LockStatus)
     */
    public int countLockRecord(Login login, LockStatus status) {
    	
        int count = 0;
        if(!login.isSupplier()) {
        	
            if(status == null) {
                count = vehicleLockRecordDao.count();
            } else {
                count = vehicleLockRecordDao.count(status);
            }
            
        } else {
        	
        	Long supplierId = login.getSupplierId();
            if(status == null) {
                count = vehicleLockRecordDao.count(supplierId);
            } else {
                count = vehicleLockRecordDao.count(status, supplierId);
            }
            
        }
        
        return count;
        
    }
    
    /*
     * (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.VehicleLockService#listLockRecord(com.demo2do.fms.admin.entity.security.Login, com.demo2do.core.entity.page.Page)
     */
    public List<VehicleSourceLockRecord> listLockRecord(Login login, Page page) {
    	
    	page.calculate();
        List<VehicleSourceLockRecord> result = new ArrayList<VehicleSourceLockRecord>();
        
        if(!login.isSupplier()) {
        	
        	result = vehicleLockRecordDaoSupport.listVehicleLockRecord(LockStatus.LOCKED, page);
        	
        } else {
        	
        	Supplier supplier = genericDaoSupport.load(Supplier.class, login.getSupplierId());
            result = vehicleLockRecordDaoSupport.listVehicleLockRecord(supplier, LockStatus.LOCKED, page);
            
        }
        
        return result;
        
    }

    /*
     * (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.VehicleLockService#listLockRecord(com.demo2do.fms.admin.entity.security.Login, com.demo2do.fms.entity.vehicle.LockStatus, com.demo2do.core.entity.page.Page)
     */
    public List<VehicleSourceLockRecord> listLockRecord(Login login, LockStatus status, Page page) {
    	
        List<VehicleSourceLockRecord> result = new ArrayList<VehicleSourceLockRecord>();
        
        if(!login.isSupplier()) {
            
        	if(status == null) {
                result = vehicleLockRecordDao.list(page.getBeginIndex(), page.getEveryPage());
            } else {
                result = vehicleLockRecordDao.list(status, page.getBeginIndex(), page.getEveryPage());
            }
            
        } else {
        	
        	Long supplierId = login.getSupplierId();
            if(status == null) {
                result = vehicleLockRecordDao.list(supplierId, page.getBeginIndex(), page.getEveryPage());
            } else {
                result = vehicleLockRecordDao.list(status, supplierId, page.getBeginIndex(), page.getEveryPage());
            }
            
        }
        
        page.calculate();
        return result;
        
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.VehicleLockService#countLockRecord(com.demo2do.fms.admin.entity.search.supplier.AbnormalCapacitySearch, java.lang.String, java.lang.String, com.demo2do.fms.admin.entity.security.Login)
     */
    public int countLockRecord(AbnormalCapacitySearch search, Login login) {

    	// 1. 判断登录用户是否是供方，如果是供方，则设置supplierId
    	if (login.isSupplier()) {
    		search.setSupplierId(login.getSupplierId());
    	}
    	
    	// 2. count lock record
    	return vehicleLockRecordDaoSupport.countVehicleLockRecord(search);
        
    }
    
    /*
     * (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.VehicleLockService#listLockRecord(com.demo2do.fms.admin.entity.search.supplier.AbnormalCapacitySearch, java.lang.String, java.lang.String, com.demo2do.fms.admin.entity.security.Login, com.demo2do.core.entity.page.Page)
     */
    public List<VehicleSourceLockRecord> searchLockRecord(AbnormalCapacitySearch search, Login login, Page page) {
        
        // 1. 判断登录用户是否是供方，如果是供方，则设置supplierId
        if (login.isSupplier()) {
        	search.setSupplierId(login.getSupplierId());
        }
        
        // 2. search lock record
        List<VehicleSourceLockRecord> records = vehicleLockRecordDaoSupport.search(search, page);
        page.calculate();
        return records;
        
    }

}
